package com.gengao.springbootcase.aop;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Component
@Aspect//Aop 要先引入依赖
@Slf4j
public class TimeAspect {
    @Around("pt()")//切入点表达式
    public Object recordTime(ProceedingJoinPoint joinPoint) throws Throwable {
//        记录开始时间
        long begin = System.currentTimeMillis();
        Object result = joinPoint.proceed();//调用原始方法运行
        long end=System.currentTimeMillis();
        log.info(joinPoint.getSignature()+"方法执行耗时{}ms",end-begin);
        return result;//@Around 通知必须有返回值 Object

//
    }

//    Aop核心概念: 连接点 通知 切入点(实际被Aop控制的方法) 切面 目标对象
//    Aop执行流程 动态代理(运行的就不是目标对象 而是代理对象)

//    Aop进阶
//    1 通知类型 @Around 环绕通知 @Before 前置通知 @After 后置通知 @AfterReturning(原始方法正常运行正常返回) @AfterThrowing 异常后通知
//    2 切入点表达式 怎么解决大量切入点表达式大量重复
    @Pointcut("execution(* com.gengao.springbootcase.*.*(..))")//如果需要改动只需要改动这一部分
    public void pt(){
    }



//    3 通知顺序 和切面类的类名有关系 但这样不好管理 可以通过添加注解@Order来实现 before数字越小越先执行 after数字越小越后执行 了解就好
//    4 切入点表达式 描述一些切入点方法的表达式
//      execution()
//      @annotation() 基于注解 可以先自己定义一个注解 然后将注解加载自己需要匹配的方法上

    @Pointcut("@annotation(com.gengao.springbootcase.aop.MyLog)")
    public void pt1(){}

//    5 连接点 spring中使用JointPoint抽象了连接点

}
